gl renderer: Moar state tracking
authorTimm Bäder <mail@baedert.org>
Fri, 24 Jul 2020 06:49:24 +0000 (08:49 +0200)
committerTimm Bäder <mail@baedert.org>
Tue, 28 Jul 2020 03:34:11 +0000 (05:34 +0200)
Track what we really need to send for inset shadows, which are used
as a border replacement in many cases.

Fishbowl says I can draw around 200-300 more switches per frame like
this too.

gsk/gl/gskglrenderer.c
gsk/gl/gskglrenderops.c
gsk/gl/gskglrenderopsprivate.h
gsk/gl/opbuffer.c
gsk/gl/opbuffer.h
gsk/resources/glsl/inset_shadow.glsl
gsk/resources/glsl/unblurred_outset_shadow.glsl

index 87774796ce1cac7f981599b8537579700c1270e3..81b9302f6da7b90e08287739abf4a09503b70c80 100644 (file)
@@ -742,15 +742,9 @@ render_border_node (GskGLRenderer   *self,
       gdk_rgba_equal (&colors[0], &colors[2]) &&
       gdk_rgba_equal (&colors[0], &colors[3]))
     {
-      OpShadow *op;
-
       ops_set_program (builder, &self->programs->inset_shadow_program);
-      op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
-      op->color = &colors[0];
-      op->outline = transform_rect (self, builder, rounded_outline);
-      op->spread = widths[0];
-      op->offset[0] = 0;
-      op->offset[1] = 0;
+      ops_set_inset_shadow (builder, transform_rect (self, builder, rounded_outline),
+                            widths[0], &colors[0], 0, 0);
 
       load_vertex_data (ops_draw (builder, NULL), node, builder);
       return;
@@ -1607,17 +1601,14 @@ render_unblurred_inset_shadow_node (GskGLRenderer   *self,
   const float dx = gsk_inset_shadow_node_get_dx (node);
   const float dy = gsk_inset_shadow_node_get_dy (node);
   const float spread = gsk_inset_shadow_node_get_spread (node);
-  OpShadow *op;
 
   g_assert (blur_radius == 0);
 
   ops_set_program (builder, &self->programs->inset_shadow_program);
-  op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
-  op->color = gsk_inset_shadow_node_peek_color (node);
-  op->outline = transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node));
-  op->spread = spread;
-  op->offset[0] = dx;
-  op->offset[1] = dy;
+  ops_set_inset_shadow (builder, transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node)),
+                        spread,
+                        gsk_inset_shadow_node_peek_color (node),
+                        dx, dy);
 
   load_vertex_data (ops_draw (builder, NULL), node, builder);
 }
@@ -1635,7 +1626,6 @@ render_inset_shadow_node (GskGLRenderer   *self,
   const GskRoundedRect *node_outline = gsk_inset_shadow_node_peek_outline (node);
   float texture_width;
   float texture_height;
-  OpShadow *op;
   int blurred_texture_id;
 
   g_assert (blur_radius > 0);
@@ -1699,12 +1689,10 @@ render_inset_shadow_node (GskGLRenderer   *self,
 
       /* Actual inset shadow outline drawing */
       ops_set_program (builder, &self->programs->inset_shadow_program);
-      op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
-      op->color = gsk_inset_shadow_node_peek_color (node);
-      op->outline = transform_rect (self, builder, &outline_to_blur);
-      op->spread = spread * scale;
-      op->offset[0] = dx * scale;
-      op->offset[1] = dy * scale;
+      ops_set_inset_shadow (builder, transform_rect (self, builder, &outline_to_blur),
+                            spread * scale,
+                            gsk_inset_shadow_node_peek_color (node),
+                            dx * scale, dy * scale);
 
       ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
         { { 0,             0              }, { 0, 1 }, },
@@ -1772,15 +1760,12 @@ render_unblurred_outset_shadow_node (GskGLRenderer   *self,
   const float spread = gsk_outset_shadow_node_get_spread (node);
   const float dx = gsk_outset_shadow_node_get_dx (node);
   const float dy = gsk_outset_shadow_node_get_dy (node);
-  OpShadow *op;
 
   ops_set_program (builder, &self->programs->unblurred_outset_shadow_program);
-  op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
-  op->color = gsk_outset_shadow_node_peek_color (node);
-  op->outline = transform_rect (self, builder, outline);
-  op->spread = spread;
-  op->offset[0] = dx;
-  op->offset[1] = dy;
+  ops_set_unblurred_outset_shadow (builder, transform_rect (self, builder, outline),
+                                   spread,
+                                   gsk_outset_shadow_node_peek_color (node),
+                                   dx, dy);
 
   load_vertex_data (ops_draw (builder, NULL), node, builder);
 }
@@ -1803,7 +1788,7 @@ render_outset_shadow_node (GskGLRenderer   *self,
   const float dy = gsk_outset_shadow_node_get_dy (node);
   GskRoundedRect scaled_outline;
   int texture_width, texture_height;
-  OpShadow *shadow;
+  OpOutsetShadow *shadow;
   int blurred_texture_id;
   int cached_tid;
   bool do_slicing;
@@ -1928,7 +1913,8 @@ render_outset_shadow_node (GskGLRenderer   *self,
       ops_set_texture (builder, blurred_texture_id);
 
       shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
-      shadow->outline = transform_rect (self, builder, outline);
+      shadow->outline.value = transform_rect (self, builder, outline);
+      shadow->outline.send = TRUE;
 
       tx1 = 0; tx2 = 1;
       ty1 = 0; ty2 = 1;
@@ -1956,7 +1942,8 @@ render_outset_shadow_node (GskGLRenderer   *self,
   ops_set_texture (builder, blurred_texture_id);
 
   shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
-  shadow->outline = transform_rect (self, builder, outline);
+  shadow->outline.value = transform_rect (self, builder, outline);
+  shadow->outline.send = TRUE;
 
   {
     const float min_x = floorf (builder->dx + outline->bounds.origin.x - spread - (blur_extra / 2.0) + dx);
@@ -2610,15 +2597,27 @@ apply_inset_shadow_op (const Program  *program,
                        const OpShadow *op)
 {
   OP_PRINT (" -> inset shadow. Color: %s, Offset: (%f, %f), Spread: %f, Outline: %s",
-            gdk_rgba_to_string (op->color),
-            op->offset[0],
-            op->offset[1],
-            op->spread,
-            gsk_rounded_rect_to_string (&op->outline));
-  glUniform4fv (program->inset_shadow.color_location, 1, (float *)op->color);
-  glUniform2fv (program->inset_shadow.offset_location, 1, op->offset);
-  glUniform1f (program->inset_shadow.spread_location, op->spread);
-  glUniform4fv (program->inset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds);
+            op->color.send ? gdk_rgba_to_string (op->color.value) : "don't send",
+            op->offset.send ? op->offset.value[0] : -1337.0,
+            op->offset.send ? op->offset.value[1] : -1337.0,
+            op->spread.send ? op->spread.value : -1337.0,
+            op->outline.send ? gsk_rounded_rect_to_string (&op->outline.value) : "don't send");
+  if (op->outline.send)
+    {
+      if (op->outline.send_corners)
+        glUniform4fv (program->inset_shadow.outline_rect_location, 3, (float *)&op->outline.value);
+      else
+        glUniform4fv (program->inset_shadow.outline_rect_location, 1, (float *)&op->outline.value);
+    }
+
+  if (op->color.send)
+    glUniform4fv (program->inset_shadow.color_location, 1, (float *)op->color.value);
+
+  if (op->spread.send)
+    glUniform1f (program->inset_shadow.spread_location, op->spread.value);
+
+  if (op->offset.send)
+    glUniform2fv (program->inset_shadow.offset_location, 1, op->offset.value);
 }
 
 static inline void
@@ -2626,18 +2625,31 @@ apply_unblurred_outset_shadow_op (const Program  *program,
                                   const OpShadow *op)
 {
   OP_PRINT (" -> unblurred outset shadow");
-  glUniform4fv (program->unblurred_outset_shadow.color_location, 1, (float *)op->color);
-  glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset);
-  glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread);
-  glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds);
+
+  if (op->outline.send)
+    {
+      if (op->outline.send_corners)
+        glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 3, (float *)&op->outline.value);
+      else
+        glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 1, (float *)&op->outline.value);
+    }
+
+  if (op->color.send)
+    glUniform4fv (program->unblurred_outset_shadow.color_location, 1, (float *)op->color.value);
+
+  if (op->spread.send)
+    glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread.value);
+
+  if (op->offset.send)
+    glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset.value);
 }
 
 static inline void
-apply_outset_shadow_op (const Program  *program,
-                        const OpShadow *op)
+apply_outset_shadow_op (const Program        *program,
+                        const OpOutsetShadow *op)
 {
   OP_PRINT (" -> outset shadow");
-  glUniform4fv (program->outset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds);
+  glUniform4fv (program->outset_shadow.outline_rect_location, 3, (float *)&op->outline.value.bounds);
 }
 
 static inline void
@@ -2694,6 +2706,7 @@ static inline void
 apply_cross_fade_op (const Program     *program,
                      const OpCrossFade *op)
 {
+  OP_PRINT (" -> Cross fade");
   /* End texture id */
   glUniform1i (program->cross_fade.source2_location, 1);
   glActiveTexture (GL_TEXTURE0 + 1);
@@ -3505,6 +3518,7 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self)
           break;
 
         case OP_CLEAR:
+          OP_PRINT ("-> CLEAR");
           glClearColor (0, 0, 0, 0);
           glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
           break;
index c6bc5b4de8a1a0ed0a5de892faf5d3ba16975895..f710041cef07c3793d93e28e9e30317deb4cf44a 100644 (file)
@@ -747,3 +747,118 @@ ops_get_buffer (RenderOpBuilder *builder)
 {
   return &builder->render_ops;
 }
+
+void
+ops_set_inset_shadow (RenderOpBuilder      *self,
+                      const GskRoundedRect  outline,
+                      float                 spread,
+                      const GdkRGBA        *color,
+                      float                 dx,
+                      float                 dy)
+{
+  ProgramState *current_program_state = get_current_program_state (self);
+  OpShadow *op;
+
+  op = ops_begin (self, OP_CHANGE_INSET_SHADOW);
+
+  if (!rounded_rect_equal (&outline, &current_program_state->inset_shadow.outline))
+    {
+      op->outline.value = outline;
+      op->outline.send = TRUE;
+      op->outline.send_corners = !rounded_rect_corners_equal (&current_program_state->inset_shadow.outline,
+                                                              &outline);
+      current_program_state->inset_shadow.outline = outline;
+    }
+  else
+    op->outline.send = FALSE;
+
+  if (spread != current_program_state->inset_shadow.spread)
+    {
+      op->spread.value = spread;
+      op->spread.send = TRUE;
+
+      current_program_state->inset_shadow.spread = spread;
+    }
+  else
+    op->spread.send = FALSE;
+
+  if (!gdk_rgba_equal (color, &current_program_state->inset_shadow.color))
+    {
+      op->color.value = color;
+      op->color.send = TRUE;
+
+      current_program_state->inset_shadow.color = *color;
+    }
+  else
+    op->color.send = FALSE;
+
+  if (dx != current_program_state->inset_shadow.dx ||
+      dy != current_program_state->inset_shadow.dy)
+    {
+      op->offset.value[0] = dx;
+      op->offset.value[1] = dy;
+      op->offset.send = TRUE;
+
+      current_program_state->inset_shadow.dx = dx;
+      current_program_state->inset_shadow.dy = dy;
+    }
+  else
+    op->offset.send = FALSE;
+}
+void
+ops_set_unblurred_outset_shadow (RenderOpBuilder      *self,
+                                 const GskRoundedRect  outline,
+                                 float                 spread,
+                                 const GdkRGBA        *color,
+                                 float                 dx,
+                                 float                 dy)
+{
+  ProgramState *current_program_state = get_current_program_state (self);
+  OpShadow *op;
+
+  op = ops_begin (self, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
+
+  if (!rounded_rect_equal (&outline, &current_program_state->unblurred_outset_shadow.outline))
+    {
+      op->outline.value = outline;
+      op->outline.send = TRUE;
+      op->outline.send_corners = !rounded_rect_corners_equal (&current_program_state->unblurred_outset_shadow.outline,
+                                                              &outline);
+      current_program_state->unblurred_outset_shadow.outline = outline;
+    }
+  else
+    op->outline.send = FALSE;
+
+  if (spread != current_program_state->unblurred_outset_shadow.spread)
+    {
+      op->spread.value = spread;
+      op->spread.send = TRUE;
+
+      current_program_state->unblurred_outset_shadow.spread = spread;
+    }
+  else
+    op->spread.send = FALSE;
+
+  if (!gdk_rgba_equal (color, &current_program_state->unblurred_outset_shadow.color))
+    {
+      op->color.value = color;
+      op->color.send = TRUE;
+
+      current_program_state->unblurred_outset_shadow.color = *color;
+    }
+  else
+    op->color.send = FALSE;
+
+  if (dx != current_program_state->unblurred_outset_shadow.dx ||
+      dy != current_program_state->unblurred_outset_shadow.dy)
+    {
+      op->offset.value[0] = dx;
+      op->offset.value[1] = dy;
+      op->offset.send = TRUE;
+
+      current_program_state->unblurred_outset_shadow.dx = dx;
+      current_program_state->unblurred_outset_shadow.dy = dy;
+    }
+  else
+    op->offset.send = FALSE;
+}
index 2ddc048dba865ef7cf244b6bcd8cbf692d19b04c..0a8bf557f9ac4f000d97f8981a93395ec47e791f 100644 (file)
@@ -122,6 +122,20 @@ typedef struct
       GdkRGBA color;
       GskRoundedRect outline;
     } border;
+    struct {
+      GskRoundedRect outline;
+      float dx;
+      float dy;
+      float spread;
+      GdkRGBA color;
+    } inset_shadow;
+    struct {
+      GskRoundedRect outline;
+      float dx;
+      float dy;
+      float spread;
+      GdkRGBA color;
+    } unblurred_outset_shadow;
   };
 } ProgramState;
 
@@ -237,6 +251,18 @@ void              ops_set_border_width   (RenderOpBuilder         *builder,
 
 void              ops_set_border_color   (RenderOpBuilder         *builder,
                                           const GdkRGBA           *color);
+void              ops_set_inset_shadow   (RenderOpBuilder         *self,
+                                          const GskRoundedRect     outline,
+                                          float                    spread,
+                                          const GdkRGBA           *color,
+                                          float                    dx,
+                                          float                    dy);
+void              ops_set_unblurred_outset_shadow   (RenderOpBuilder         *self,
+                                                     const GskRoundedRect     outline,
+                                                     float                    spread,
+                                                     const GdkRGBA           *color,
+                                                     float                    dx,
+                                                     float                    dy);
 
 GskQuadVertex *   ops_draw               (RenderOpBuilder        *builder,
                                           const GskQuadVertex     vertex_data[GL_N_VERTICES]);
index b85127b5dd5cbbbe6150c7b3797e9648f9cc41e5..496308c5aef1b5143d4aa3ab01fc684323624cdc 100644 (file)
@@ -18,7 +18,7 @@ static guint op_sizes[OP_LAST] = {
   sizeof (OpColorMatrix),
   sizeof (OpBlur),
   sizeof (OpShadow),
-  sizeof (OpShadow),
+  sizeof (OpOutsetShadow),
   sizeof (OpBorder),
   sizeof (OpBorder),
   sizeof (OpBorder),
index 4c33babf97b1466bacf4b6cddb3da59c286fd557..76609c82a170b051a058c6315ae98fc2a894cf97 100644 (file)
@@ -41,11 +41,30 @@ typedef enum
   OP_LAST
 } OpKind;
 
+
+typedef struct { float value; guint send: 1; }    FloatUniformValue;
+typedef struct { float value[2]; guint send: 1; } Float2UniformValue;
+typedef struct { GskRoundedRect value; guint send: 1; guint send_corners: 1; } RRUniformValue;
+typedef struct { const GdkRGBA *value; guint send: 1; } RGBAUniformValue;
+
 /* OpNode are allocated within OpBuffer.pos, but we keep
  * a secondary index into the locations of that buffer
  * from OpBuffer.index. This allows peeking at the kind
  * and quickly replacing existing entries when necessary.
  */
+typedef struct
+{
+  RRUniformValue outline;
+  FloatUniformValue spread;
+  Float2UniformValue offset;
+  RGBAUniformValue color;
+} OpShadow;
+
+typedef struct
+{
+  RRUniformValue outline;
+} OpOutsetShadow;
+
 typedef struct
 {
   guint  pos;
@@ -128,14 +147,6 @@ typedef struct
   float dir[2];
 } OpBlur;
 
-typedef struct
-{
-  GskRoundedRect outline;
-  float spread;
-  float offset[2];
-  const GdkRGBA *color;
-} OpShadow;
-
 typedef struct
 {
   float widths[4];
index 238540c7317a1211a1234c17e6586dcf46950357..5b43779fe8a2d55350becb98537754ccf8ac8abc 100644 (file)
@@ -35,9 +35,9 @@ _IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 void main() {
   vec2 frag = get_frag_coord();
 
-  float alpha = clamp (rounded_rect_coverage(decode_rect(transformed_outside_outline), frag) -
-                       rounded_rect_coverage(decode_rect(transformed_inside_outline), frag),
-                       0.0, 1.0);
+  float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), frag) -
+                      rounded_rect_coverage(decode_rect(transformed_inside_outline), frag),
+                      0.0, 1.0);
 
   setOutputColor(final_color * alpha);
 }
index 419605e092fb11b48220f138b31e4db29a27fc8b..a789155b6429403252b41691f9075fa2296e7302 100644 (file)
@@ -41,3 +41,4 @@ void main() {
 
   setOutputColor(final_color * alpha);
 }
+